//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.IO;
using OpenLS.Spreadsheet.Formats.Biff.Tokens;

namespace OpenLS.Spreadsheet.Formats.Biff
{
    internal static class AddressHelper
    {
        public static RangeReferenceAddress ReadRangeReferenceAddress16(FormulaReadContext context)
        {
            switch (context.Type)
            {
                case FormulaReadContextType.Default:
                    {

                        int firstRow = context.ReadUInt16();
                        int lastRow = context.ReadUInt16();
                        CellReferenceAddress first;
                        CellReferenceAddress last;
                        {
                            int column;
                            bool absoluteRow, absoluteColumn;
                            ReadColumnAndFlags16(context.Reader, out column, out absoluteColumn, out absoluteRow);
                            first = new CellReferenceAddress(firstRow, column, absoluteRow, absoluteColumn);
                        }
                        {
                            int column;
                            bool absoluteRow, absoluteColumn;
                            ReadColumnAndFlags16(context.Reader, out column, out absoluteColumn, out absoluteRow);
                            last = new CellReferenceAddress(lastRow, column, absoluteRow, absoluteColumn);
                        }
                        return new RangeReferenceAddress(first, last);
                    }
                case FormulaReadContextType.ExternName:
                    {
                        ushort short1 = context.ReadUInt16();
                        ushort row1 = context.ReadUInt16();
                        ushort row2 = context.ReadUInt16();
                        ushort column1 = context.ReadUInt16();
                        ushort column2= context.ReadUInt16();
                        var first = new CellReferenceAddress(row1, column1, false, false);
                        var last = new CellReferenceAddress(row2, column2, false, false);
                        return new RangeReferenceAddress(first, last);
                    }
                default: throw new NotSupportedException();
            }

        }

        public static void ReadColumnAndFlags16(BinaryReader reader, out int columnIndex, out bool absoluteColumn,
                                                out bool absoluteRow)
        {
            ushort flag2 = reader.ReadUInt16();
            absoluteColumn = (flag2 & 0x4000) == 0;
            absoluteRow = (flag2 & 0x8000) == 0;
            int c = (flag2 & 0x3FFF);
          //  if (!absoluteColumn)
            //    columnIndex = (sbyte) c;
           // else
                columnIndex = c;
        }


        internal static Range ToRange(RangeAddress rangeAddress, Worksheet worksheet)
        {
            if (rangeAddress.TopLeft.Equals(rangeAddress.BottomRight))
                return new SingleCellRange(worksheet[rangeAddress.TopLeft]);
            //\\
            return new MultiCellsRange(worksheet, rangeAddress);
        }

        public static void WriteRangeReferenceAddress16(RangeReferenceAddress rangeAddress, FormulaWriteContext context)
        {
            switch (context.Type)
            {
                case FormulaReadContextType.Default:
                    {
                        context.Writer.Write((ushort)rangeAddress.First.Row);
                        context.Writer.Write((ushort)rangeAddress.Last.Row);
                        WriteColumnAndFlags16((ushort) rangeAddress.First.Column, rangeAddress.First.AbsoluteRow,
                                              rangeAddress.First.AbsoluteColumn, context.Writer);
                        WriteColumnAndFlags16((ushort) rangeAddress.Last.Column, rangeAddress.Last.AbsoluteRow,
                                              rangeAddress.Last.AbsoluteColumn, context.Writer);
                    }
                    break;
                case FormulaReadContextType.ExternName:
                    {
                        throw new NotImplementedException();
                    }
                default: throw new NotSupportedException();
            }

        }

        private static void WriteColumnAndFlags16(ushort column, bool absoluteRow, bool absoluteColumn, BinaryWriter writer)
        {
            ushort value = column;
            if (!absoluteColumn)
                value |= 0x4000;
            if (!absoluteRow)
                value |= 0x8000;
            writer.Write(value);
        }

    }
}